﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Minio.DataModel;
using Modules.Attachment;
using Modules.Commander;
using Modules.Common;
using Modules.Constructor;
using Modules.Corp;
using Modules.Manager.Repositories;
using Modules.Person;
using Modules.Project.Entitys;
using Modules.Project.EventArgs;
using Modules.Project.Models;
using Modules.Project.Repositories;
using Modules.System.Attachment;
using Modules.System.Security;
using Modules.System.User;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Entity;
using PmSoft.Events;
using PmSoft.Exceptions;
using PmSoft.Repositories;
using System.ComponentModel.Design;
using System.Linq;
using System.Reflection;
using static Modules.Person.PersonConstants;
using static Modules.Project.ProjectConstants;
using ConstructorInfo = Modules.Constructor.ConstructorInfo;

namespace Modules.Project
{
    /// <summary>
    /// 项目信息相关业务逻辑
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class ProjectService
    {
        private readonly ProjectInfoRepository repository;
        private readonly ProjectAttachmentService projectAttachmentService;
        private readonly ProjectGroupMemberService projectGroupMemberService;
        private readonly ManagerInfoRepository managerInfoRepository;
        private readonly ProjectCorpService projectCorpService;
        private readonly SecurityService securityService;
        private readonly ConstructorService constructorService;
        private readonly CorpService corpService;
        private readonly IApplicationContext applicationContext;
        private readonly CommanderProjectService commanderProjectService;
        private readonly ProjectStatusChangeRecordService projectStatusChangeRecordService;
        private readonly ProjectNumIndexer projectNumIndexer;
        private readonly ILogger logger;
        private readonly PersonService personService;
        private readonly IEventBus eventBus;

        public ProjectService(ProjectInfoRepository repository,
            IApplicationContext applicationContext,
            ILogger<ProjectService> logger,
            ProjectAttachmentService projectAttachmentService,
            SecurityService securityService,
            ProjectGroupMemberService projectGroupMemberService,
            ManagerInfoRepository managerInfoRepository,
            ConstructorService constructorService,
            ProjectCorpService projectCorpService,
            ProjectStatusChangeRecordService projectStatusChangeRecordService,
            CommanderProjectService commanderProjectService,
            CorpService corpService,
            ProjectNumIndexer projectNumIndexer,
            PersonService personService,
            IEventBus eventBus
            )
        {
            this.repository = repository;
            this.projectAttachmentService = projectAttachmentService;
            this.applicationContext = applicationContext;
            this.logger = logger;
            this.securityService = securityService;
            this.projectGroupMemberService = projectGroupMemberService;
            this.managerInfoRepository = managerInfoRepository;
            this.constructorService = constructorService;
            this.projectCorpService = projectCorpService;
            this.projectStatusChangeRecordService = projectStatusChangeRecordService;
            this.commanderProjectService = commanderProjectService;
            this.corpService = corpService;
            this.projectNumIndexer = projectNumIndexer;
            this.personService = personService;
            this.eventBus = eventBus;
        }

        /// <summary>
        /// author:hzj date:2023/12/05 describe:创建项目
        /// </summary>
        /// <param name="projectInfo"></param>
        //public void CreateProjectInfo(ProjectInfo projectInfo, decimal lumpContractorCorpAmount, decimal? supervisorCorpAmount, DateTime lumpContractorCorpStartDate, DateTime lumpContractorCorpEndDate, DateTime? supervisorCorpStartDate, DateTime? supervisorCorpEndDate, bool hasSupervisor, List<string> attachments, List<string> positionAttachments, List<string> noSupervisorAttachments, List<string> earnestAttachments, int? commanderId)
        //{
        //    //新增项目信息
        //    if (repository.ExistsByPrjNum(projectInfo))
        //        throw new BusinessException($"项目编号：{projectInfo.PrjNum} 已存在，不能创建");

        // if (repository.ExistsByPrjCode(projectInfo)) throw new
        // BusinessException($"项目代码：{projectInfo.GgProjectCode} 已存在，不能创建");

        // try { //开始事务 applicationContext.Transaction.Begin(); var numSerialNum =
        // GetProjectNumAndSerialNumber(projectInfo.AreaCode); projectInfo.PrjNum
        // = numSerialNum.ProjectNum; projectInfo.SerialNumber = numSerialNum.SerialNumber; repository.Insert(projectInfo);

        // //新增projectcorp表 总包和监理单位数据 //ProjectCorp projectCorp = new ProjectCorp() //{ // ProjectId
        // = projectInfo.ProjectId, // CorpId = projectInfo.LumpContractorCorpId ?? 0, // Role =
        // 项目参建单位类型.总承包单位, // ContractAmount = lumpContractorCorpAmount, // CreateTime =
        // DateTime.Now, // StartDate = lumpContractorCorpStartDate, // EndDate =
        // lumpContractorCorpEndDate, //}; //projectCorpService.CreateProjectCorpNoTransaction(projectCorp);

        // #region 监理

        // if (hasSupervisor) { var projectCorp = new ProjectCorp() { ProjectId =
        // projectInfo.ProjectId, CorpId = projectInfo.SupervisorCorpId ?? 0, Role = 项目参建单位类型.监理,
        // ContractAmount = supervisorCorpAmount.Value, CreateTime = DateTime.Now, StartDate =
        // supervisorCorpStartDate.Value, EndDate = supervisorCorpEndDate.Value, };
        // projectCorpService.CreateProjectCorpNoTransaction(projectCorp); }

        // #endregion 监理

        // #region 附件

        // var ProjectAttachments =
        // projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId,
        // 附件类型.中标通知书, 项目附件租户.Project).Select(a => a.Id); projectAttachmentService.Deleted(ProjectAttachments);

        // foreach (var item in attachments) { ProjectAttachment projectAttachment = new() { Id =
        // Guid.NewGuid().ToString().Replace("-", ""), AttachmentId = item, ObjectId =
        // projectInfo.ProjectId.ToString(), Tenant = 项目附件租户.Project, AttachmentType = 附件类型.中标通知书,
        // CreateTime = DateTime.Now }; projectAttachmentService.Create(projectAttachment); } if
        // (!hasSupervisor) { var ProjectAttachments2 =
        // projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId,
        // 附件类型.无监理证明, 项目附件租户.Project).Select(a => a.Id); projectAttachmentService.Deleted(ProjectAttachments2);

        // foreach (var item in noSupervisorAttachments) { ProjectAttachment projectAttachment =
        // new() { Id = Guid.NewGuid().ToString().Replace("-", ""), AttachmentId = item, ObjectId =
        // projectInfo.ProjectId.ToString(), Tenant = 项目附件租户.Project, AttachmentType = 附件类型.无监理证明,
        // CreateTime = DateTime.Now }; projectAttachmentService.Create(projectAttachment); } }

        // if (projectInfo.PositionCount > 1) { var ProjectAttachments3 =
        // projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId,
        // 附件类型.多地施工证明, 项目附件租户.Project).Select(a => a.Id); projectAttachmentService.Deleted(ProjectAttachments3);

        // foreach (var item in positionAttachments) { ProjectAttachment projectAttachment = new() {
        // Id = Guid.NewGuid().ToString().Replace("-", ""), AttachmentId = item, ObjectId =
        // projectInfo.ProjectId.ToString(), Tenant = 项目附件租户.Project, AttachmentType = 附件类型.多地施工证明,
        // CreateTime = DateTime.Now }; projectAttachmentService.Create(projectAttachment); } }

        // if (projectInfo.HasEarnestMoney.HasValue && projectInfo.HasEarnestMoney.Value) { var
        // ProjectAttachments4 =
        // projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId,
        // 附件类型.担保文件, 项目附件租户.Project).Select(a => a.Id); projectAttachmentService.Deleted(ProjectAttachments4);

        // foreach (var item in earnestAttachments) { ProjectAttachment projectAttachment = new() {
        // Id = Guid.NewGuid().ToString().Replace("-", ""), AttachmentId = item, ObjectId =
        // projectInfo.ProjectId.ToString(), Tenant = 项目附件租户.Project, AttachmentType = 附件类型.担保文件,
        // CreateTime = DateTime.Now }; projectAttachmentService.Create(projectAttachment); } }

        // #endregion 附件

        // #region 建设单位

        // //新增建设单位信息 ConstructorInfo constructorInfo = new() { Name = projectInfo.BuildCorpName,
        // Code = projectInfo.BuildCorpCode, CreateTime = DateTime.Now, LinkTel =
        // projectInfo.BuildPhoneNum, }; constructorService.CreateConstructor(constructorInfo,
        // "123456"); //新增projectcorp表 建设单位数据 //ProjectCorpQuery query = new ProjectCorpQuery() //{
        // // ProjectId = projectInfo.ProjectId, // CorpId = constructorInfo.ConstructorId, // Role
        // = 项目参建单位类型.建设单位, //}; //projectCorp = projectCorpService.GetProjectCorps(query, 1,
        // 1).FirstOrDefault() ?? new ProjectCorp(); ////更新项目信息时需要更新建设单位信息 //if (projectCorp.Id > 0)
        // //{ // projectCorp.StartDate = projectInfo.ContractStartDate; // projectCorp.EndDate =
        // projectInfo.EndDate ?? DateTime.Now; // projectCorpService.Update(projectCorp); //}
        // //else //{ // projectCorp = new ProjectCorp(); // projectCorp.ProjectId =
        // projectInfo.ProjectId; // projectCorp.Role = 项目参建单位类型.建设单位; // projectCorp.CorpId =
        // constructorInfo.ConstructorId; // projectCorp.StartDate = projectInfo.ContractStartDate;
        // // projectCorp.EndDate = projectInfo.EndDate ?? DateTime.Now; //
        // projectCorpService.CreateProjectCorpNoTransaction(projectCorp); //}

        // #endregion 建设单位

        // #region 指挥部

        // if (commanderId.HasValue) { commanderProjectService.InsertCommanderProject(new
        // CommanderProject() { CommanderId = commanderId.Value, ProjectId = projectInfo.ProjectId
        // }); }

        // #endregion 指挥部

        //        applicationContext.Transaction.Complete();
        //    }
        //    catch (Exception ex)
        //    {
        //        applicationContext.Transaction.Abort();//回滚事务
        //        logger.LogError(ex, $"CreateProjectInfo Exception prjNum:{projectInfo.PrjNum}");
        //        throw new BusinessException("写入项目数据失败");
        //    }
        //}

        /// <summary>
        /// 无事务创建项目信息
        /// </summary>
        /// <param name="projectInfo"></param>
        /// <param name=""></param>
        /// <param name="attachments"></param>
        /// <returns></returns>
        public ProjectInfo CreateProjectInfoNoTransaction(ProjectInfo projectInfo)
        {
            projectInfo.NeedCompletData = true;
            projectInfo.PrjStatus = projectInfo.ContractStartDate < DateTime.Now ? 项目状态.在建 : 项目状态.筹备;
            repository.Insert(projectInfo);
            return projectInfo;
        }

        /// <summary>
        /// author:hzj date:2023/12/05 describe:修改项目
        /// </summary>
        /// <param name="projectInfo"></param>
        /**     public void UpdateProjectInfo(ProjectInfo projectInfo, IEnumerable<string> attachments, IEnumerable<string> earnestAttachments, IEnumerable<string> noSupervisorAttachments, IEnumerable<string> positionAttachments)
              {
                  if (repository.ExistsByPrjNum(projectInfo, projectInfo.ProjectId))
                      throw new BusinessException($"项目编号：{projectInfo.PrjNum} 已存在，不能编辑");

                  if (repository.ExistsByPrjCode(projectInfo, projectInfo.ProjectId))
                      throw new BusinessException($"项目代码：{projectInfo.GgProjectCode} 已存在，不能编辑");
                  try
                  {
                      //开始事务
                      applicationContext.Transaction.Begin();
                      repository.Update(projectInfo);

                      #region 附件

                      if (attachments.Any())
                      {
                          var ProjectAttachments = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project).Select(a => a.Id);
                          projectAttachmentService.Deleted(ProjectAttachments);
                          foreach (var item in attachments)
                          {
                              ProjectAttachment projectAttachment = new()
                              {
                                  Id = Guid.NewGuid().ToString().Replace("-", ""),
                                  AttachmentId = item,
                                  ObjectId = projectInfo.ProjectId.ToString(),
                                  Tenant = 项目附件租户.Project,
                                  AttachmentType = 附件类型.中标通知书,
                                  CreateTime = DateTime.Now
                              };
                              projectAttachmentService.Create(projectAttachment);
                          }
                      }
                      if (earnestAttachments.Any())
                      {
                          var ProjectAttachments = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project).Select(a => a.Id);
                          projectAttachmentService.Deleted(ProjectAttachments);
                          foreach (var item in earnestAttachments)
                          {
                              ProjectAttachment projectAttachment = new()
                              {
                                  Id = Guid.NewGuid().ToString().Replace("-", ""),
                                  AttachmentId = item,
                                  ObjectId = projectInfo.ProjectId.ToString(),
                                  Tenant = 项目附件租户.Project,
                                  AttachmentType = 附件类型.担保文件,
                                  CreateTime = DateTime.Now
                              };
                              projectAttachmentService.Create(projectAttachment);
                          }
                      }
                      if (noSupervisorAttachments.Any())
                      {
                          var ProjectAttachments = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.无监理证明, 项目附件租户.Project).Select(a => a.Id);
                          projectAttachmentService.Deleted(ProjectAttachments);
                          foreach (var item in noSupervisorAttachments)
                          {
                              ProjectAttachment projectAttachment = new()
                              {
                                  Id = Guid.NewGuid().ToString().Replace("-", ""),
                                  AttachmentId = item,
                                  ObjectId = projectInfo.ProjectId.ToString(),
                                  Tenant = 项目附件租户.Project,
                                  AttachmentType = 附件类型.无监理证明,
                                  CreateTime = DateTime.Now
                              };
                              projectAttachmentService.Create(projectAttachment);
                          }
                      }
                      if (positionAttachments.Any())
                      {
                          var ProjectAttachments = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.多地施工证明, 项目附件租户.Project).Select(a => a.Id);
                          projectAttachmentService.Deleted(ProjectAttachments);
                          foreach (var item in positionAttachments)
                          {
                              ProjectAttachment projectAttachment = new()
                              {
                                  Id = Guid.NewGuid().ToString().Replace("-", ""),
                                  AttachmentId = item,
                                  ObjectId = projectInfo.ProjectId.ToString(),
                                  Tenant = 项目附件租户.Project,
                                  AttachmentType = 附件类型.多地施工证明,
                                  CreateTime = DateTime.Now
                              };
                              projectAttachmentService.Create(projectAttachment);
                          }
                      }

                      #endregion 附件

                      applicationContext.Transaction.Complete();
                  }
                  catch (Exception ex)
                  {
                      applicationContext.Transaction.Abort();//回滚事务
                      logger.LogError(ex, $"UpdateProjectInfo Exception prjNum:{projectInfo.PrjNum}");
                      throw new BusinessException("编辑项目数据失败");
                  }
              }
*/

        public void CreateProjectInfo(ProjectInfo projectInfo, CorpInfo supervisorCorp, decimal supervisorAmount, int? commanderId, IEnumerable<ProjectAttachment> attachments)
        {
            try
            {
                applicationContext.Transaction.Begin();
                //step1：新建项目

                #region 新建项目

                repository.Insert(projectInfo);

                #endregion 新建项目

                //step2：创建总包管理组

                #region 创建总包管理组

                var projectGroupService = applicationContext.GetService<ProjectGroupService>();
                projectGroupService.CreateProjectGroup(
                    new ProjectGroup()
                    {
                        ProjectId = projectInfo.ProjectId,
                        CorpId = projectInfo.LumpContractorCorpId,
                        Name = "项目部班组",
                        CreateTime = DateTime.Now,
                        StartDate = projectInfo.ContractStartDate,
                        EndDate = projectInfo.ContractEndDate,
                        IsManagerGroup = true
                    });

                #endregion 创建总包管理组

                //step3：关联建设单位

                #region 关联建设单位

                if (projectInfo.BuildCorpId == 0)
                {
                    var constructor = new ConstructorInfo()
                    {
                        Code = projectInfo.BuildCorpCode,
                        Name = projectInfo.BuildCorpName,
                        LinkTel = projectInfo.BuildPhoneNum,
                        Type = ConstructorType.企业
                    };
                    constructorService.CreateConstructorNoTransaction(constructor);
                    projectInfo.BuildCorpId = constructor.ConstructorId;
                }

                #endregion 关联建设单位

                //step4：关联监理

                #region 关联监理

                if (projectInfo.HasSupervisor)
                {
                    if (supervisorCorp.CorpId > 0) corpService.Update(supervisorCorp);
                    else
                        corpService.CreateCorpInfoNoTransaction(supervisorCorp);
                    projectInfo.SupervisorCorpId = supervisorCorp.CorpId;
                    ProjectCorp projectCorp = new ProjectCorp();
                    projectCorp.ProjectId = projectInfo.ProjectId;
                    projectCorp.CorpId = supervisorCorp.CorpId;
                    projectCorp.Role = 项目参建单位类型.监理;
                    projectCorp.ContractAmount = supervisorAmount;
                    projectCorp.StartDate = projectInfo.ContractStartDate;
                    projectCorp.EndDate = projectInfo.ContractEndDate;
                    projectCorpService.CreateProjectCorpNoTransaction(projectCorp, null, null, true);
                }

                #endregion 关联监理

                //step5：关联指挥部

                #region 关联指挥部

                if (commanderId.HasValue)
                {
                    commanderProjectService.InsertCommanderProject(new CommanderProject() { CommanderId = commanderId.Value, ProjectId = projectInfo.ProjectId });
                }

                #endregion 关联指挥部

                //step6：关联附件

                #region 关联附件

                if (attachments.Any())
                {
                    var letter = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project);
                    var position = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.多地施工证明, 项目附件租户.Project);
                    var noSupervisor = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.无监理证明, 项目附件租户.Project);
                    var security = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project);
                    projectAttachmentService.Deleted(letter.Select(i => i.Id));
                    projectAttachmentService.Deleted(position.Select(i => i.Id));
                    projectAttachmentService.Deleted(noSupervisor.Select(i => i.Id));
                    projectAttachmentService.Deleted(security.Select(i => i.Id));
                    foreach (var attachment in attachments)
                    {
                        attachment.ObjectId = projectInfo.ProjectId.ToString();
                        projectAttachmentService.Create(attachment);
                    }
                }

                repository.Update(projectInfo);

                #endregion 关联附件

                applicationContext.Transaction.Complete();
            }
            catch (BusinessException ex)
            {
                applicationContext.Transaction.Abort();
                throw new BusinessException(ex.Message);
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, ex.Message);
                throw new BusinessException("创建项目失败");
            }
        }

        /// <summary>
        /// 更新项目信息（登记注册无事务版）
        /// </summary>
        /// <param name="projectInfo">项目基础信息</param>
        /// <param name="supervisorCorp">监理信息</param>
        /// <param name="supervisorAmount">监理合同金额</param>
        /// <param name="attachments">所有附件信息</param>
        /// <exception cref="BusinessException"></exception>
        public void UpdateProjectInfo(ProjectInfo projectInfo, CorpInfo supervisorCorp, decimal supervisorAmount, int? commanderId, IEnumerable<ProjectAttachment> attachments)
        {
            //step1：查询旧数据
            var oldProjectInfo = repository.Get(projectInfo.ProjectId) ?? throw new BusinessException("修改项目不存在");
            var projectGroupService = applicationContext.GetService<ProjectGroupService>();
            var oldProjectGroups = projectGroupService.GetProjectGroupsByProjectId(projectInfo.ProjectId);
            var oldProjectCorps = projectCorpService.GetProjectCorpsByProjectId(projectInfo.ProjectId);

            try
            {
                applicationContext.Transaction.Begin();
                //step2：更新总包管理组

                #region 更新总包管理组

                if (oldProjectInfo.LumpContractorCorpId != projectInfo.LumpContractorCorpId)
                {
                    var group = oldProjectGroups.FirstOrDefault(i => i.CorpId == oldProjectInfo.LumpContractorCorpId) ?? throw new BusinessException("总包管理组不存在");
                    group.CorpId = projectInfo.LumpContractorCorpId;
                    projectGroupService.UpdateProjectGroup(group);
                }

                #endregion 更新总包管理组

                //step3：关联建设单位

                #region 关联建设单位

                if (oldProjectInfo.BuildCorpId != projectInfo.BuildCorpId && projectInfo.BuildCorpId == 0)
                {
                    var constructor = new ConstructorInfo()
                    {
                        Code = projectInfo.BuildCorpCode,
                        Name = projectInfo.BuildCorpName,
                        LinkTel = projectInfo.BuildPhoneNum,
                        Type = ConstructorType.企业
                    };
                    constructorService.CreateConstructorNoTransaction(constructor);
                    projectInfo.BuildCorpId = constructor.ConstructorId;
                }

                #endregion 关联建设单位

                //step4：关联监理

                #region 关联监理

                if (projectInfo.HasSupervisor)
                {
                    ProjectCorp projectCorp = new ProjectCorp();
                    if (oldProjectInfo.SupervisorCorpId.HasValue && oldProjectInfo.SupervisorCorpId > 0)
                        projectCorp = oldProjectCorps.FirstOrDefault(i => i.CorpId == oldProjectInfo.SupervisorCorpId) ?? new ProjectCorp();
                    if (supervisorCorp.CorpId == 0)
                        corpService.CreateCorpInfoNoTransaction(supervisorCorp);
                    projectInfo.SupervisorCorpId = supervisorCorp.CorpId;
                    projectCorp.ProjectId = projectInfo.ProjectId;
                    projectCorp.CorpId = supervisorCorp.CorpId;
                    projectCorp.Role = 项目参建单位类型.监理;
                    projectCorp.ContractAmount = supervisorAmount;
                    projectCorp.StartDate = projectInfo.ContractStartDate;
                    projectCorp.EndDate = projectInfo.ContractEndDate;
                    if (projectCorp.Id > 0)
                    {
                        projectCorpService.Update(projectCorp);
                    }
                    else
                    {
                        projectCorpService.CreateProjectCorpNoTransaction(projectCorp, null, null, true);
                    }
                }

                #endregion 关联监理

                //step5：关联指挥部

                #region 关联指挥部

                if (commanderId.HasValue)
                {
                    commanderProjectService.InsertCommanderProject(new CommanderProject() { CommanderId = commanderId.Value, ProjectId = projectInfo.ProjectId });
                }

                #endregion 关联指挥部

                //step6：关联附件

                #region 关联附件

                if (attachments.Any())
                {
                    var letter = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project);
                    var position = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.多地施工证明, 项目附件租户.Project);
                    var noSupervisor = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.无监理证明, 项目附件租户.Project);
                    var security = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project);
                    projectAttachmentService.Deleted(letter.Select(i => i.Id));
                    projectAttachmentService.Deleted(position.Select(i => i.Id));
                    projectAttachmentService.Deleted(noSupervisor.Select(i => i.Id));
                    projectAttachmentService.Deleted(security.Select(i => i.Id));
                    foreach (var attachment in attachments)
                    {
                        attachment.ObjectId = projectInfo.ProjectId.ToString();
                        projectAttachmentService.Create(attachment);
                    }
                }

                #endregion 关联附件

                #region 更新项目信息(可新增)

                repository.Update(projectInfo);

                #endregion 更新项目信息(可新增)

                applicationContext.Transaction.Complete();
            }
            catch (BusinessException ex)
            {
                applicationContext.Transaction.Abort();
                throw new BusinessException(ex.Message);
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();
                logger.LogError(ex, ex.Message);
                throw new BusinessException("更新项目失败");
            }
        }

        /// <summary>
        /// 更新项目信息（新增/修改）
        /// </summary>
        /// <param name="projectInfo">项目基础信息</param>
        /// <param name="constructor">建设单位信息</param>
        /// <param name="SupervisorCorp">监理信息</param>
        /// <param name="SupervisorAmount">监理合同金额</param>
        /// <param name="attachments">所有附件信息</param>
        /// <exception cref="BusinessException"></exception>

        //public void UpdateProjectInfo(ProjectInfo projectInfo, ConstructorInfo? constructor, CorpInfo? SupervisorCorp, decimal SupervisorAmount, int? commanderId, IEnumerable<ProjectAttachment> attachments)
        //{
        //    try
        //    {
        //        applicationContext.Transaction.Begin();

        //        #region 更新项目信息(可新增)

        //        if (projectInfo.ProjectId > 0) repository.Update(projectInfo);
        //        else repository.Insert(projectInfo);

        //        #endregion 更新项目信息(可新增)

        //        #region 更新总承包信息(必定会有总承包信息)

        //        //if (projectInfo.LumpContractorCorpId != null && projectInfo.LumpContractorCorpId > 0)
        //        //{
        //        //    ProjectCorp projectCorp = projectCorpService.GetProjectCorpByProjectIdAndCorpId(projectInfo.ProjectId, projectInfo.LumpContractorCorpId ?? 0, 项目参建单位类型.总承包单位) ?? new ProjectCorp();
        //        //    projectCorp.ProjectId = projectInfo.ProjectId;
        //        //    projectCorp.CorpId = projectInfo.LumpContractorCorpId ?? 0;
        //        //    projectCorp.Role = 项目参建单位类型.总承包单位;
        //        //    projectCorp.ContractAmount = projectInfo.ContractAmount ?? 0;
        //        //    projectCorp.StartDate = projectInfo.ContractStartDate;
        //        //    projectCorp.EndDate = projectInfo.ContractEndDate;

        //        //    if (projectCorp.Id == 0) projectCorpService.CreateProjectCorpNoTransaction(projectCorp);
        //        //    else projectCorpService.Update(projectCorp);
        //        //}

        //        #endregion 更新总承包信息(必定会有总承包信息)

        //        #region 更新建设单位信息(可新增)

        //        if (constructor != null)
        //        {
        //            if (constructor.ConstructorId > 0)
        //                constructorService.Update(constructor);
        //            else
        //                constructorService.CreateConstructorNoTransaction(constructor, "Xzhr.123456");

        //            projectInfo.BuildCorpId = constructor.ConstructorId;
        //        }

        //        #endregion 更新建设单位信息(可新增)

        //        #region 指挥部

        //        if (commanderId.HasValue)
        //        {
        //            commanderProjectService.InsertCommanderProject(new CommanderProject() { CommanderId = commanderId.Value, ProjectId = projectInfo.ProjectId });
        //        }

        //        #endregion 指挥部

        //        #region 更新监理信息(可新增)

        //        if (SupervisorCorp != null)
        //        {
        //            if (SupervisorCorp.CorpId > 0) corpService.Update(SupervisorCorp);
        //            else
        //                corpService.CreateCorpInfoNoTransaction(SupervisorCorp, "Xzhr.123456");
        //            ProjectCorp projectCorp = projectCorpService.GetProjectCorpByProjectIdAndCorpId(projectInfo.ProjectId, projectInfo.SupervisorCorpId ?? 0, 项目参建单位类型.监理) ?? new ProjectCorp();
        //            projectCorp.ProjectId = projectInfo.ProjectId;
        //            projectCorp.CorpId = SupervisorCorp.CorpId;
        //            projectCorp.Role = 项目参建单位类型.监理;
        //            projectCorp.ContractAmount = SupervisorAmount;
        //            projectCorp.StartDate = projectInfo.ContractStartDate;
        //            projectCorp.EndDate = projectInfo.ContractEndDate;
        //            if (projectCorp.Id == 0) projectCorpService.CreateProjectCorpNoTransaction(projectCorp);
        //            else projectCorpService.Update(projectCorp);
        //            projectInfo.SupervisorCorpId = SupervisorCorp.CorpId;
        //        }

        //        #endregion 更新监理信息(可新增)

        //        #region 项目附件更新

        //        if (attachments.Any())
        //        {
        //            var letter = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project);
        //            var position = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.多地施工证明, 项目附件租户.Project);
        //            var noSupervisor = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.无监理证明, 项目附件租户.Project);
        //            var security = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project);
        //            projectAttachmentService.Deleted(letter.Select(i => i.Id));
        //            projectAttachmentService.Deleted(position.Select(i => i.Id));
        //            projectAttachmentService.Deleted(noSupervisor.Select(i => i.Id));
        //            projectAttachmentService.Deleted(security.Select(i => i.Id));
        //            foreach (var attachment in attachments)
        //            {
        //                attachment.ObjectId = projectInfo.ProjectId.ToString();
        //                projectAttachmentService.Create(attachment);
        //            }
        //        }

        //        #endregion 项目附件更新

        //        repository.Update(projectInfo);
        //        applicationContext.Transaction.Complete();
        //    }
        //    catch (Exception ex)
        //    {
        //        applicationContext.Transaction.Abort();//回滚事务
        //        logger.LogError(ex, $"UpdateProjectInfo Exception prjNum:{projectInfo.PrjNum}");
        //        throw new BusinessException("编辑项目数据失败," + ex.Message);
        //    }
        //}

        /// <summary>
        /// 创建项目信息(登记注册无事务版)
        /// </summary>
        /// <param name="projectInfo"></param>
        /// <param name="supervisorCorp"></param>
        /// <param name="supervisorAmount"></param>
        /// <param name="commanderId"></param>
        /// <param name="attachments"></param>
        public void CreateProjectInfoNoTransaction(ProjectInfo projectInfo, CorpInfo supervisorCorp, decimal supervisorAmount, int? commanderId, IEnumerable<ProjectAttachment> attachments)
        {
            //step1：新建项目

            #region 新建项目

            repository.Insert(projectInfo);

            #endregion 新建项目

            //step2：创建总包管理组

            #region 创建总包管理组

            var projectGroupService = applicationContext.GetService<ProjectGroupService>();
            projectGroupService.CreateProjectGroup(
                new ProjectGroup()
                {
                    ProjectId = projectInfo.ProjectId,
                    CorpId = projectInfo.LumpContractorCorpId,
                    Name = "项目部班组",
                    CreateTime = DateTime.Now,
                    StartDate = projectInfo.ContractStartDate,
                    EndDate = projectInfo.ContractEndDate,
                    IsManagerGroup = true
                });

            #endregion 创建总包管理组

            //step3：关联建设单位

            #region 关联建设单位

            if (projectInfo.BuildCorpId == 0)
            {
                var constructor = new ConstructorInfo()
                {
                    Code = projectInfo.BuildCorpCode,
                    Name = projectInfo.BuildCorpName,
                    LinkTel = projectInfo.BuildPhoneNum,
                    Type = ConstructorType.企业
                };
                constructorService.CreateConstructorNoTransaction(constructor);
                projectInfo.BuildCorpId = constructor.ConstructorId;
            }

            #endregion 关联建设单位

            //step4：关联监理

            #region 关联监理

            if (projectInfo.HasSupervisor)
            {
                if (supervisorCorp.CorpId > 0) corpService.Update(supervisorCorp);
                else
                    corpService.CreateCorpInfoNoTransaction(supervisorCorp);
                projectInfo.SupervisorCorpId = supervisorCorp.CorpId;
                ProjectCorp projectCorp = new ProjectCorp();
                projectCorp.ProjectId = projectInfo.ProjectId;
                projectCorp.CorpId = supervisorCorp.CorpId;
                projectCorp.Role = 项目参建单位类型.监理;
                projectCorp.ContractAmount = supervisorAmount;
                projectCorp.StartDate = projectInfo.ContractStartDate;
                projectCorp.EndDate = projectInfo.ContractEndDate;
                projectCorpService.CreateProjectCorpNoTransaction(projectCorp, null, null, true);
            }

            #endregion 关联监理

            //step5：关联指挥部

            #region 关联指挥部

            if (commanderId.HasValue)
            {
                commanderProjectService.InsertCommanderProject(new CommanderProject() { CommanderId = commanderId.Value, ProjectId = projectInfo.ProjectId });
            }

            #endregion 关联指挥部

            //step6：关联附件

            #region 关联附件

            if (attachments.Any())
            {
                var letter = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project);
                var position = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.多地施工证明, 项目附件租户.Project);
                var noSupervisor = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.无监理证明, 项目附件租户.Project);
                var security = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project);
                projectAttachmentService.Deleted(letter.Select(i => i.Id));
                projectAttachmentService.Deleted(position.Select(i => i.Id));
                projectAttachmentService.Deleted(noSupervisor.Select(i => i.Id));
                projectAttachmentService.Deleted(security.Select(i => i.Id));
                foreach (var attachment in attachments)
                {
                    attachment.ObjectId = projectInfo.ProjectId.ToString();
                    projectAttachmentService.Create(attachment);
                }
            }

            repository.Update(projectInfo);

            #endregion 关联附件
        }

        /// <summary>
        /// 更新项目信息（登记注册无事务版）
        /// </summary>
        /// <param name="projectInfo">项目基础信息</param>
        /// <param name="supervisorCorp">监理信息</param>
        /// <param name="supervisorAmount">监理合同金额</param>
        /// <param name="attachments">所有附件信息</param>
        /// <exception cref="BusinessException"></exception>
        public void UpdateProjectInfoNoTransaction(ProjectInfo projectInfo, CorpInfo supervisorCorp, decimal supervisorAmount, int? commanderId, IEnumerable<ProjectAttachment> attachments)
        {
            //step1：查询旧数据
            var oldProjectInfo = repository.Get(projectInfo.ProjectId) ?? throw new BusinessException("修改项目不存在");
            var projectGroupService = applicationContext.GetService<ProjectGroupService>();
            var oldProjectGroups = projectGroupService.GetProjectGroupsByProjectId(projectInfo.ProjectId);
            var oldProjectCorps = projectCorpService.GetProjectCorpsByProjectId(projectInfo.ProjectId);

            //step2：更新总包管理组

            #region 更新总包管理组

            if (oldProjectInfo.LumpContractorCorpId != projectInfo.LumpContractorCorpId)
            {
                var group = oldProjectGroups.FirstOrDefault(i => i.CorpId == oldProjectInfo.LumpContractorCorpId) ?? throw new BusinessException("总包管理组不存在");
                group.CorpId = projectInfo.LumpContractorCorpId;
                projectGroupService.UpdateProjectGroup(group);
            }

            #endregion 更新总包管理组

            //step3：关联建设单位

            #region 关联建设单位

            if (oldProjectInfo.BuildCorpId != projectInfo.BuildCorpId && projectInfo.BuildCorpId == 0)
            {
                var constructor = new ConstructorInfo()
                {
                    Code = projectInfo.BuildCorpCode,
                    Name = projectInfo.BuildCorpName,
                    LinkTel = projectInfo.BuildPhoneNum,
                    Type = ConstructorType.企业
                };
                constructorService.CreateConstructorNoTransaction(constructor);
                projectInfo.BuildCorpId = constructor.ConstructorId;
            }
            if ( projectInfo.BuildCorpId > 0) { 
            var constructor= constructorService.GetConstructorInfo(projectInfo.BuildCorpId)??throw new BusinessException("所选建设单位不存在");
                if (string.IsNullOrEmpty(constructor.Code)) {
                    constructor.Code= projectInfo.BuildCorpCode;
                    constructorService.Update(constructor);
                }
            }
            #endregion 关联建设单位

            //step4：关联监理

            #region 关联监理

            if (projectInfo.HasSupervisor)
            {
                ProjectCorp projectCorp = new ProjectCorp();
                if (oldProjectInfo.SupervisorCorpId.HasValue && oldProjectInfo.SupervisorCorpId > 0)
                    projectCorp = oldProjectCorps.FirstOrDefault(i => i.CorpId == oldProjectInfo.SupervisorCorpId) ?? new ProjectCorp();
                if (supervisorCorp.CorpId == 0)
                    corpService.CreateCorpInfoNoTransaction(supervisorCorp);
                projectInfo.SupervisorCorpId = supervisorCorp.CorpId;
                projectCorp.ProjectId = projectInfo.ProjectId;
                projectCorp.CorpId = supervisorCorp.CorpId;
                projectCorp.Role = 项目参建单位类型.监理;
                projectCorp.ContractAmount = supervisorAmount;
                projectCorp.StartDate = projectInfo.ContractStartDate;
                projectCorp.EndDate = projectInfo.ContractEndDate;
                if (projectCorp.Id > 0)
                {
                    projectCorpService.Update(projectCorp);
                }
                else
                {
                    projectCorpService.CreateProjectCorpNoTransaction(projectCorp, null, null, true);
                }
            }

            #endregion 关联监理

            //step5：关联指挥部

            #region 关联指挥部

            if (commanderId.HasValue)
            {
                commanderProjectService.InsertCommanderProject(new CommanderProject() { CommanderId = commanderId.Value, ProjectId = projectInfo.ProjectId });
            }

            #endregion 关联指挥部

            //step6：关联附件

            #region 关联附件

            if (attachments.Any())
            {
                var letter = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project);
                var position = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.多地施工证明, 项目附件租户.Project);
                var noSupervisor = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.无监理证明, 项目附件租户.Project);
                var security = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project);
                projectAttachmentService.Deleted(letter.Select(i => i.Id));
                projectAttachmentService.Deleted(position.Select(i => i.Id));
                projectAttachmentService.Deleted(noSupervisor.Select(i => i.Id));
                projectAttachmentService.Deleted(security.Select(i => i.Id));
                foreach (var attachment in attachments)
                {
                    attachment.ObjectId = projectInfo.ProjectId.ToString();
                    projectAttachmentService.Create(attachment);
                }
            }

            #endregion 关联附件

            #region 更新项目信息(可新增)

            repository.Update(projectInfo);

            #endregion 更新项目信息(可新增)
        }

        public void UpdateProjectInfoNoTransaction(ProjectInfo projectInfo, IEnumerable<string> attachments)
        {
            if (repository.ExistsByPrjNum(projectInfo, projectInfo.ProjectId))
                throw new BusinessException($"项目编号：{projectInfo.PrjNum} 已存在，不能编辑");

            if (repository.ExistsByPrjCode(projectInfo, projectInfo.ProjectId))
                throw new BusinessException($"项目代码：{projectInfo.GgProjectCode} 已存在，不能编辑");
            repository.Update(projectInfo);

            #region 附件

            if (attachments.Any())
            {
                var ProjectAttachments = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.中标通知书, 项目附件租户.Project).Select(a => a.Id);
                projectAttachmentService.Deleted(ProjectAttachments);
                foreach (var item in attachments)
                {
                    ProjectAttachment projectAttachment = new()
                    {
                        Id = Guid.NewGuid().ToString().Replace("-", ""),
                        AttachmentId = item,
                        ObjectId = projectInfo.ProjectId.ToString(),
                        Tenant = 项目附件租户.Project,
                        AttachmentType = 附件类型.中标通知书,
                        CreateTime = DateTime.Now
                    };
                    projectAttachmentService.Create(projectAttachment);
                }
            }

            #endregion 附件
        }

        /// <summary>
        /// author:hzj date:2023/12/05 describe:完善项目信息(完善信息不能修改已存在的信息)
        /// </summary>
        /// <param name="projectInfo">项目信息</param>
        /// <param name="earnestAttachments">担保附件</param>
        public void CompletProjectInfo(ProjectInfo projectInfo, List<AttachmentsForm<int>>? earnestAttachments)
        {
            try
            {
                //开始事务
                applicationContext.Transaction.Begin();

                #region 附件

                //仅不存在该类型附件时需要完善
                var attachmentIds = projectAttachmentService.GetProjectAttachmentsByObjectIdAndType(projectInfo.ProjectId, 附件类型.担保文件, 项目附件租户.Project).Select(a => a.Id);
                projectAttachmentService.Deleted(attachmentIds);
                if (earnestAttachments != null)
                {
                    foreach (var item in earnestAttachments)
                    {
                        ProjectAttachment projectAttachment = new()
                        {
                            Id = Guid.NewGuid().ToString().Replace("-", ""),
                            AttachmentId = item.AttachmentId,
                            ObjectId = projectInfo.ProjectId.ToString(),
                            Tenant = 项目附件租户.Project,
                            AttachmentType = 附件类型.担保文件,
                            CreateTime = DateTime.Now
                        };
                        projectAttachmentService.Create(projectAttachment);
                    }
                }

                #endregion 附件

                repository.Update(projectInfo);
                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CompletProjectInfo Exception prjNum:{projectInfo.PrjNum}");
                throw new BusinessException("完善项目数据失败");
            }
        }

        /// <summary>
        /// author:hzj date:2023/12/05 describe:转换需要完善数据的实体
        /// </summary>
        /// <param name="newObject"></param>
        /// <param name="oldObject"></param>
        /// <returns></returns>
        public ProjectInfo ConvertCompletInfo(ProjectInfo newObject, ProjectInfo? oldObject)
        {
            if (oldObject == null) return newObject;
            ProjectInfo temp = JsonConvert.DeserializeObject<ProjectInfo>(JsonConvert.SerializeObject(oldObject)) ?? new ProjectInfo();
            foreach (PropertyInfo property in temp.GetType().GetProperties())
            {
                // 忽略非公共属性
                if (!property.CanWrite)
                {
                    continue;
                }
                // 获取属性值
                object? oldValue = property.GetValue(oldObject);
                object? newValue = property.GetValue(newObject);
                if (oldValue == null || (oldValue is string str && string.IsNullOrWhiteSpace(str)))
                {
                    // 字符串为空或者WhitespaceStringType时，覆盖属性值
                    property.SetValue(temp, newValue);
                }
                else if (oldValue is DateTime date && date == DateTime.MinValue)
                {
                    // 日期为MinValue时，覆盖属性值
                    property.SetValue(temp, newValue);
                }
            }
            return temp;
        }

        /// <summary>
        /// author:hzj date:2023/12/05 describe:绑定劳资专管员
        /// </summary>
        /// <param name="managerInfo">劳资专管员信息</param>
        /// <param name="managerInfo">现场管理人员</param>
        /// <param name="projectId">项目Id</param>
        /// <param name="password">劳资专管员密码</param>
        public void BindManager(ManagerInfo managerInfo, ProjectGroupMember projectGroupMember, int projectId, string password)
        {
            try
            {
                applicationContext.Transaction.Begin();//开始事务
                                                       //登陆安全表更新
                if (managerInfo.ManagerId == 0)
                {
                    SysSecurity security = new()
                    {
                        Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4),
                        UserType = UserType.Manager,
                    };
                    securityService.Create(security);
                    managerInfo.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
                    managerInfo.ProjectId = projectId;
                    managerInfoRepository.Insert(managerInfo);
                }
                else
                {
                    if (managerInfo.ProjectId == 0)
                    {
                        managerInfo.ProjectId = projectId;
                        managerInfoRepository.Update(managerInfo);
                    }
                }
                //项目基础信息表更新
                ProjectInfo? projectInfo = repository.Get(projectId) ?? throw new BusinessException("项目信息不存在");
                //原项目的管理员项目为空
                if (projectInfo.ManagerId != null && projectInfo.ManagerId != managerInfo.ManagerId)
                {
                    var oldManagerInfo = managerInfoRepository.Get(projectInfo.ManagerId);
                    if (oldManagerInfo != null)
                    {
                        oldManagerInfo.ProjectId = 0;
                        managerInfoRepository.Update(oldManagerInfo);

                        #region 将项目原来在场的劳资专管员设置为离场

                        PersonInfo? personInfo = personService.GetPersonByCardNo(oldManagerInfo.Cardno);
                        if (personInfo != null)
                        {
                            IEnumerable<ProjectGroupMember> oldOnlineGroupMembers = projectGroupMemberService.GetProjectGroupMembersByProjectId(projectId).Where(a => a.PersonId == personInfo.PersonId && a.Status == 进出场状态.进场);
                            if (oldOnlineGroupMembers != null && oldOnlineGroupMembers.Count() > 0)
                            {
                                foreach (var item in oldOnlineGroupMembers)
                                {
                                    item.EndDate = DateTime.Now;
                                    item.Status = 进出场状态.离场;
                                    projectGroupMemberService.Update(item);
                                }
                            }
                        }

                        #endregion 将项目原来在场的劳资专管员设置为离场
                    }
                }
                projectInfo.ManagerId = managerInfo.ManagerId;
                repository.Update(projectInfo);

                #region 现场管理人员数据修改

                projectGroupMember.Status = 进出场状态.进场;
                projectGroupMember.StartDate = DateTime.Now;
                projectGroupMemberService.Update(projectGroupMember);

                #endregion 现场管理人员数据修改

                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"BindManager Exception cardno:{managerInfo.Cardno}");
                throw new BusinessException("绑定项目管理员数据失败");
            }
        }

        /// <summary>
        /// 根据项目主键获取项目信息
        /// </summary>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public ProjectInfo? GetProjectInfo(int projectId)
        {
            return repository.Get(projectId);
        }

        /// <summary>
        /// 根据项目编号获取项目信息
        /// </summary>
        /// <param name="prjNum"></param>
        /// <returns></returns>
        public ProjectInfo? GetProjectInfoByPrjNum(string prjNum)
        {
            int? id = projectNumIndexer.GetId(prjNum);
            if (id.HasValue && id > 0)
                return GetProjectInfo(id.Value);
            return null;
        }

        /// <summary>
        /// 根据项目名称获取项目信息
        /// </summary>
        /// <param name="projectName"></param>
        /// <returns></returns>
        public ProjectInfo? GetProjectInfoByName(string projectName)
        {
            return repository.GetProjectInfoByName(projectName);
        }

        /// <summary>
        /// 根据项目招标标段编号获取项目信息
        /// </summary>
        /// <param name="biddingSectionNums"></param>
        /// <returns></returns>
        public IEnumerable<ProjectInfo> GetProjectInfosByBiddingSectionNum(IEnumerable<string> biddingSectionNums)
        {
            return repository.GetProjectInfosByBiddingSectionNum(biddingSectionNums);
        }

        /// <summary>
        /// 适用于全局项目查询
        /// </summary>
        /// <param name="query"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<ProjectInfo> GetProjectInfos(ProjectInfoQuery query, int pageIndex, int pageSize)
        {
            return repository.GetProjectInfos(query, pageIndex, pageSize);
        }

        public IEnumerable<ProjectInfo> GetProjectInfos(IEnumerable<int> ids)
        {
            return repository.PopulateEntitiesByEntityIds(ids);
        }

        /// <summary>
        /// 适用于项目管理员项目查询
        /// </summary>
        /// <param name="query"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IPagedList<ProjectInfo> GetProjectInfosByManagerId(ProjectInfoQuery query, int pageIndex, int pageSize)
        {
            return repository.GetProjectInfos(query, pageIndex, pageSize);
        }

        /// <summary>
        /// 获取项目管理员的所有项目
        /// </summary>
        /// <param name="managerId"></param>
        /// <returns></returns>
        public IEnumerable<ProjectInfo> GetProjectInfosByManagerId(int managerId)
        {
            return repository.GetProjectInfosByManagerId(managerId);
        }

        public void Delete(int id)
        {
            projectNumIndexer.Remove(id);//删除索引
            repository.DeleteByEntityId(id);
        }

        public bool UpdateProjectAuditStatus(ProjectInfo data, ProjectConstants.项目审核状态 auditStatus, string auditReason)
        {
            try
            {
                applicationContext.Transaction.Begin();
                if (data.ContractStartDate != null && auditStatus == 项目审核状态.通过)
                {
                    data.PrjStatus = data.ContractStartDate < DateTime.Now ? 项目状态.在建 : 项目状态.筹备;
                    projectStatusChangeRecordService.Create(new ProjectStatusChangeRecord()
                    {
                        OldStatus = null,
                        NewStatus = data.PrjStatus.Value,
                        ProjectId = data.ProjectId,
                        CreateTime = DateTime.Now,
                        EffectiveDate = data.ContractStartDate,
                        Remark = "项目审核通过"
                    });
                }
                data.AuditReason = auditReason;
                data.AuditStatus = auditStatus;
                Update(data);
                //var res = repository.UpdateAuditStatus(data, auditStatus, auditReason);
                applicationContext.Transaction.Complete();
                return true;
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"UpdateProjectAuditStatus Exception prjNum:{data.PrjNum}");
                throw new BusinessException("审核项目失败");
            }
        }

        public IEnumerable<ProjectInfo> GetProjects(IEnumerable<int> projectIds)
        {
            return repository.PopulateEntitiesByEntityIds(projectIds);
        }

        /// <summary>
        /// 生成项目编号和流水号
        /// </summary>
        /// <param name="areaCode"></param>
        /// <returns></returns>
        public (string ProjectNum, int SerialNumber) GetProjectNumAndSerialNumber(int areaCode)
        {
            DateTime time = DateTime.Now;
            ProjectInfo? data = repository.GetProjectInfoByMaxSerialNumber(areaCode, time);
            int SerialNumber = 1;
            if (data != null)
                SerialNumber = data.SerialNumber + 1;
            string ProjectNum = $"{SerialNumberType.项目.GetDescription()}-{areaCode}{time.ToString("yyMMdd")}-{SerialNumber.ToString().PadLeft(4, '0')}";
            return (ProjectNum, SerialNumber);
        }

        /// <summary>
        /// 生成项目编号
        /// </summary>
        /// <param name="areaCode"></param>
        /// <returns></returns>
        public string GetProjectNum(int areaCode)
        {
            DateTime time = DateTime.Now;
            int serialNumber = GetProjectInfoByMaxSerialNumber(areaCode);
            return $"{SerialNumberType.项目.GetDescription()}-{areaCode}{time.ToString("yyMMdd")}-{serialNumber.ToString().PadLeft(4, '0')}";
        }

        /// <summary>
        /// 生成流水号
        /// </summary>
        /// <param name="areaCode">行政区划id，六位数</param>
        /// <returns></returns>
        public int GetProjectInfoByMaxSerialNumber(int areaCode)
        {
            DateTime time = DateTime.Now;
            ProjectInfo? data = repository.GetProjectInfoByMaxSerialNumber(areaCode, time);
            if (data == null)
                return 1;
            else return data.SerialNumber + 1;
        }

        public IEnumerable<ProjectInfo> GetProjectInfoByProjectIds(IEnumerable<int> projectIds)
        {
            return repository.PopulateEntitiesByEntityIds(projectIds);
        }

        public IEnumerable<ProjectInfo> GetProjectInfosByStatus(项目状态 status)
        {
            return repository.GetProjectInfosByStatus(status);
        }

        //public IEnumerable<ProjectInfo> GetAll()
        //{
        //    return repository.GetAll();
        //}

        /// <summary>
        /// 修改项目状态
        /// </summary>
        /// <param name="projectId">项目id</param>
        /// <param name="newStatus">修改后状态</param>
        public void UpdateProjectStatus(int projectId, 项目状态 newStatus, DateTime? effectiveDate, DateTime? endDate = null)
        {
            try
            {
                applicationContext.Transaction.Begin();
                ProjectInfo? projectInfo = GetProjectInfo(projectId);
                if (projectInfo == null)
                    throw new BusinessException("项目信息不存在");

                #region 增加一条项目状态变更记录信息

                ProjectStatusChangeRecord projectStatusChangeRecord = new()
                {
                    ProjectId = projectInfo.ProjectId,
                    OldStatus = projectInfo.PrjStatus,
                    EffectiveDate = DateTime.Now.Date,
                    NewStatus = newStatus,
                    CreateTime = DateTime.Now
                };
                if (effectiveDate.HasValue) projectStatusChangeRecord.EffectiveDate = effectiveDate.Value;
                else projectStatusChangeRecord.EffectiveDate = DateTime.Now;
                projectStatusChangeRecordService.Create(projectStatusChangeRecord);

                #endregion 增加一条项目状态变更记录信息

                #region 修改项目状态

                projectInfo.PrjStatus = newStatus;
                if (endDate.HasValue)
                    projectInfo.EndDate = endDate.Value;
                repository.Update(projectInfo);

                #endregion 修改项目状态

                if (newStatus == 项目状态.完工)
                {
                    var projectCorps = projectCorpService.GetProjectCorpsByProjectId(projectId);
                    var needUpdates = projectCorps.Where(i => i.Role == 项目参建单位类型.监理);
                    foreach (var item in needUpdates)
                    {
                        item.EndDate = endDate ?? DateTime.Now;
                        projectCorpService.Update(item);
                    }
                }
                applicationContext.Transaction.Complete();
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"项目状态修改失败:{projectId}");
                throw new BusinessException("项目状态修改失败");
            }
            //发布状态变更时间
            eventBus.PublishTo(this, new ProjectStatusChangeEventArgs(projectId));
        }

        public bool ExistsProjectInfo(int projectId, int managerId)
        {
            return repository.ExistsProjectInfo(projectId, managerId);
        }

        /// <summary>
        /// 修改项目信息（只修改基础表）
        /// </summary>
        /// <param name="projectInfo"></param>
        public void Update(ProjectInfo projectInfo)
        {
            repository.Update(projectInfo);
        }

        /// <summary>
        /// 获取首页信息
        /// </summary>
        /// <returns></returns>
        public HomeStatistic GetHomeStatistic()
        {
            return repository.GetHomeStatistic();
        }

        /// <summary>
        /// 通过上下文获取当前登录者身份信息的管辖项目Id
        /// </summary>
        /// <returns></returns>
        public IEnumerable<int> GetAllProjectIdsByApplicationContext()
        {
            return repository.GetAllProjectIdsByApplicationContext();
        }

        /// <summary>
        /// 验证是否已审核的项目，并返回审核不通过的项目
        /// </summary>
        /// <param name="id"></param>
        /// <param name="userType"></param>
        /// <param name="failProject"></param>
        /// <returns></returns>
        public bool HsAuditProject(int id, UserType userType, out ProjectInfo? failProject)
        {
            bool hasProject = false;
            failProject = null;
            if (userType == UserType.Manager)
            {
                IEnumerable<ProjectInfo> projectInfos = GetProjectInfosByManagerId(id);
                hasProject = projectInfos.Any(a => a.AuditStatus == 项目审核状态.通过);
                failProject = projectInfos.FirstOrDefault(a => a.AuditStatus == 项目审核状态.不通过);
            }
            if (userType == UserType.Corp)
            {
                IEnumerable<ProjectInfo> projectInfos = GetProjectInfosByLumpContractorCorpId(id);
                hasProject = projectInfos.Any(a => a.AuditStatus == 项目审核状态.通过);
                failProject = projectInfos.FirstOrDefault(a => a.AuditStatus == 项目审核状态.不通过);
            }
            return hasProject;
        }

        /// <summary>
        /// 获取总包的所有项目集合
        /// </summary>
        /// <param name="corpId">总包企业ID</param>
        /// <returns></returns>
        public IEnumerable<ProjectInfo> GetProjectInfosByLumpContractorCorpId(int corpId)
        {
            return repository.GetProjectInfosByLumpContractorCorpId(corpId);
        }

        /// <summary>
        /// 获取建设单位的所有项目集合
        /// </summary>
        /// <param name="constructorId">建设单位ID</param>
        /// <returns></returns>
        public IEnumerable<ProjectInfo> GetProjectInfosByConstructorId(int constructorId)
        {
            return repository.GetProjectInfosByConstructorId(constructorId);
        }
    }
}